package middleware

import (
	"context"
	"kstar-gf-api/library/response"
	"strings"

	"github.com/gogf/gf/v2/encoding/gjson"
	"github.com/gogf/gf/v2/errors/gcode"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/ghttp"
	"github.com/gogf/gf/v2/util/gconv"
)

// 校验登录
func MiddlewareGlobalHandler(r *ghttp.Request) {
	trimRequestParams(r)
	systemOpen(r)
	requestLog(r)
	r.Middleware.Next()
	exceptionHandler(r)
	responHandler(r)
}

// trimRequestParams 处理请求参数的首尾空格和换行符
func trimRequestParams(r *ghttp.Request) {
	// 处理GET查询参数
	queryMap := r.GetQueryMap()
	if len(queryMap) > 0 {
		for key, value := range queryMap {
			r.SetQuery(key, trimValue(value))
		}
	}

	// 处理POST/PUT/PATCH等请求的Body参数
	if r.Method != "GET" && r.Method != "HEAD" && r.Method != "OPTIONS" {
		// 获取表单参数
		formMap := r.GetFormMap()
		if len(formMap) > 0 {
			for key, value := range formMap {
				r.SetForm(key, trimValue(value))
			}
		}
	}
}

// trimValue 递归处理值中的字符串
func trimValue(value interface{}) interface{} {
	switch v := value.(type) {
	case string:
		return strings.TrimSpace(v)
	case []string:
		for i, s := range v {
			v[i] = strings.TrimSpace(s)
		}
		return v
	case map[string]interface{}:
		for key, val := range v {
			v[key] = trimValue(val)
		}
		return v
	case []interface{}:
		for i, item := range v {
			v[i] = trimValue(item)
		}
		return v
	default:
		return v
	}
}

// 检查服务是否开启，配置文件中server.serverOpen设置为true时，系统将不对外提供服务
func systemOpen(r *ghttp.Request) {
	isOpen := true
	serverOpen, err := g.Cfg().Get(context.TODO(), "server.serverOpen")
	if err != nil {
		isOpen = false
	} else {
		isOpen = serverOpen.Bool()
	}

	if !isOpen {
		response.MaintReturn(r)
	}
}

// 记录请求日志
func requestLog(r *ghttp.Request) {
	reqParam := r.GetRequestMap(nil)
	reqStr := gjson.MustEncode(reqParam)
	g.Log("api").Info(r.GetCtx(), "[request] url: "+r.RequestURI+", param: "+gconv.String(reqStr))
}

// 异常处理
func exceptionHandler(r *ghttp.Request) {
	if err := r.GetError(); err != nil {
		// 记录到自定义错误日志文件
		g.Log("exception").Error(context.TODO(), err)
		//返回固定的友好信息
		r.Response.ClearBuffer()
		response.InnerErrorReturn(r, err)
	}
}

// 返回处理中间件
func responHandler(r *ghttp.Request) {
	// 如果已经有返回内容，那么该中间件什么也不做
	if r.Response.BufferLength() > 0 || r.Response.Status != 200 {
		return
	}

	var err = r.GetError()
	var res = r.GetHandlerResponse()
	var code gcode.Code = gcode.CodeOK

	if err != nil {
		code = gerror.Code(err)
		if code == gcode.CodeNil {
			code = gcode.CodeInternalError
		}
		response.JsonExit(r, code.Code(), err.Error(), nil)

	} else {
		response.JsonExit(r, code.Code(), code.Message(), res)
	}
}
